package com.service.totalauth.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.service.config.constant.ApiUrlConstants;
import com.service.config.utils.IdUtil;
import com.service.config.utils.JsonXMLUtils;
import com.service.config.utils.Result;
import com.service.config.utils.StringUtils;
import com.service.totalauth.dao.CompanyInfoDao;
import com.service.totalauth.dao.ProgrammeApiBindDao;
import com.service.totalauth.dto.AuthorizationDto;
import com.service.totalauth.entity.*;
import com.service.totalauth.service.OrdinaryAuthService;
import com.service.totalauth.service.PortalUserService;
import com.service.totalauth.service.UserAuthLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.service.config.constant.ApiUrlConstants.URL_FIRST;
import static com.service.config.constant.Constant.*;
import static com.service.config.utils.DesUtil.decodeToString;
import static com.service.config.utils.DesUtil.decodeUrlToString;

/**
 * 授权终端用户认证表(AuthorizationUser)表服务实现类
 *
 * @author makejava
 * @since 2021-12-03 09:38:43
 */
@Service("OrdinaryAuthService")
public class OrdinaryAuthServiceImpl implements OrdinaryAuthService {
    private static final Logger LOG = LoggerFactory.getLogger(OrdinaryAuthServiceImpl.class);

    @Resource
    private ProgrammeApiBindDao programmeApiBindDao;
    @Resource
    RestTemplate restTemplate;
    @Resource
    private UserAuthLogService userAuthLogService;
    @Resource
    private PortalUserService portalUserService;
    @Resource
    private QueryMiniProgrammeServiceImpl queryMiniProgrammeService;
    @Resource
    private CompanyInfoDao companyInfoDao;
    @Resource
    private CloudCampusApi cloudCampusApi;

    /**
     * 华为云管理portal直接访问接口,接口进行放行操作，这个操作获取不到用户的信息
     * @param authorizationDto
     * @return
     * @throws Exception
     */
    @Override
    public Result checkQyWeiUser(AuthorizationDto authorizationDto,String wxAuth,String wxtoken)  {
        try {
            ProgrammeApiBind programmeApiBind;
            if (StringUtils.isEmpty(authorizationDto.getProgrammeInfoBindId())) {
                programmeApiBind =  getProgrammeApiBindByWxAuth(wxAuth);
            }else {
                programmeApiBind = getProgrammeApiBind(authorizationDto);
            }
            if (programmeApiBind == null) {
                return Result.failure(QY_NOT_CONFIG,"方案和api等信息还未绑定，请联系该网络的管理员"); // 参数错误
            }
            CompanyInfo companyInfo = companyInfoDao.queryById(programmeApiBind.getCompanyInfoId());
            if (companyInfo == null) {
                return Result.failure(QY_NOT_CONFIG,QY_NOT_CONFIG_DESC); // 参数错误
            }
            //访客突然成为企业微信的员工则需要查询其身份并授权
            authorizationDto.setProgrammeInfoBindId(programmeApiBind.getId());
            Map auth = auth(authorizationDto);
            if (auth.isEmpty()) {
                UserAuthLog userAuthLog = new UserAuthLog();
                userAuthLog.setStatus(false);
                insertAuthorizationUser(programmeApiBind,userAuthLog,authorizationDto,companyInfo);
                return Result.failure("认证失败");
            }
            UserAuthLog userAuthLog = new UserAuthLog();
            userAuthLog.setStatus(true);
            insertAuthorizationUser(programmeApiBind,userAuthLog,authorizationDto,companyInfo);
            //认证结果
            return Result.ok();
        }catch (Exception e) {
            LOG.error(e.getMessage());
            return Result.failure(AUTH_FLAIRE,AUTH_FLAIRE_DESC); // 参数错误
        }
    }

    /**
     * 通过wxAuth查询绑定id
     * @param wxAuth
     * @return
     */
    private ProgrammeApiBind getProgrammeApiBindByWxAuth(String wxAuth) {
        ProgrammeApiBind programmeApiBind = programmeApiBindDao.queryByWxAuth(wxAuth);
        if(null==programmeApiBind)
        {
            return null;
        }
        if(StringUtils.isEmpty(programmeApiBind.getCompanyInfoId()))
        {
            return null;
        }
        return programmeApiBind;
    }
    /**
     * 无密码方案
     * @param authorizationDto
     * @return
     */
    private Map auth(AuthorizationDto authorizationDto) throws Exception {
        //获取方案，微信账号，云管账号绑定关系
        ProgrammeApiBind programmeApiBind = getProgrammeApiBind(authorizationDto);
        if(null == programmeApiBind)
        {
            return Collections.EMPTY_MAP;
        }
        //查询云管账号
        PortalUser portalUser = portalUserService.queryById(programmeApiBind.getPortalUserId());
        if (portalUser == null) {
            return Collections.EMPTY_MAP;
        }
        // 认证授权
        String auth = auth(portalUser.getTenantName(), portalUser.getTenantPwd(), portalUser.getDomain(), authorizationDto);
        if (StringUtils.isEmpty(auth)) {
            return Collections.EMPTY_MAP;
        }
        Map map = new HashMap();
        map.put("auth",auth);
        return map;
    }

    /**
     * 授权终端
     * @param username
     * @param password
     * @param domain
     * @param authorizationDto
     * @return
     * @throws Exception
     */
    private String auth(String username, String password, String domain, AuthorizationDto authorizationDto) throws Exception {
        HttpHeaders requestHeaders = queryMiniProgrammeService.getHttpHeaders();
        //获取云管的认证token
        HttpHeaders token = cloudCampusApi.getTokenRedis(username, password, domain, requestHeaders);
        if (token == null) {
            return null;
        }
        authorizationDto.setUserName(username);
        //发起授权
        return setAuthorizationUser(token, domain, authorizationDto);
    }

    /**
     * 认证日志列表
     * @param
     * @param authorizationDto
     * @param companyInfo
     */
    private void insertAuthorizationUser(ProgrammeApiBind programmeApiBind,UserAuthLog userAuthLog, AuthorizationDto authorizationDto,CompanyInfo companyInfo) throws Exception {
        userAuthLog.setId(IdUtil.getStringId());
        userAuthLog.setAuthTime(new Date());
        userAuthLog.setCompanyInfoId(companyInfo.getId());
        userAuthLog.setApMac(authorizationDto.getApmac());
        userAuthLog.setSsid(decodeToString(authorizationDto.getSsid()));
        userAuthLog.setSiteId(authorizationDto.getSiteId());
        userAuthLog.setPortalUserId(programmeApiBind.getPortalUserId());
        userAuthLog.setNodeIp(authorizationDto.getNodeIp());
        userAuthLog.setTerminalIp(authorizationDto.getUaddress());
        userAuthLog.setTerminalMac(authorizationDto.getUmac());
        userAuthLog.setProgrammeInfoId(programmeApiBind.getProgrammeInfoId());
        userAuthLogService.insert(userAuthLog);
    }

    /**
     * 授权终端用户
     * @param requestHeaders
     * @param authorizationDto
     * @return
     * @throws Exception
     */

    private String setAuthorizationUser(HttpHeaders requestHeaders,String domain, AuthorizationDto authorizationDto) throws Exception {
        try {
            Map map = new HashMap();
            Authorization authorizationUser = new Authorization();
            authorizationUser.setDeviceMac(authorizationDto.getApmac());
            String ssid = authorizationDto.getSsid();
            for (int i = 0 ;i< 20; i++) {
                ssid = decodeUrlToString(ssid);
            }
            if (ssid.contains(" ")) {
                ssid = ssid.replaceAll(" ","+");
            }
            authorizationUser.setSsid(ssid);
            authorizationDto.setSsid(ssid);
            authorizationUser.setTerminalIpV4(authorizationDto.getUaddress());
            if (authorizationDto.getNodeIp() != null) {
                authorizationUser.setNodeIp(authorizationDto.getNodeIp());
            }
            authorizationUser.setTerminalMac(authorizationDto.getUmac());
            if (authorizationDto.getUserName() != null && !"".equals(authorizationDto.getUserName())) {
                authorizationUser.setUserName(authorizationDto.getUserName());
            }
            map = JSONObject.parseObject(JsonXMLUtils.obj2json(authorizationUser));
            HttpEntity<Map> requestEntity = new HttpEntity<Map>(map, requestHeaders);
            ResponseEntity<JSONObject> response = restTemplate.postForEntity(URL_FIRST.concat(domain).concat(ApiUrlConstants.AUTHORIZATION_URL_NOT), requestEntity, JSONObject.class);
            JSONObject jsonObject = response.getBody();
            LOG.info("jsonObject : "+ jsonObject);
            return jsonObject.getString("psessionid");
        }catch (Exception e) {
            LOG.error(e.getMessage());
            return null;
        }
    }
    public ProgrammeApiBind getProgrammeApiBind(AuthorizationDto authorizationDto)
    {
        ProgrammeApiBind programmeApiBind = programmeApiBindDao.queryById(authorizationDto.getProgrammeInfoBindId());
        if(null == programmeApiBind)
        {
            return null;
        }
        if(StringUtils.isEmpty(programmeApiBind.getCompanyInfoId()))
        {
            return null;
        }
        return programmeApiBind;
    }
}
